package io.youngledo.usb.license;

import lombok.extern.slf4j.Slf4j;

/// 功能门控工具
///
/// 提供运行时功能检查机制，控制专业版功能的访问。
///
/// ## 使用方式
///
/// ### 方式1: 简单检查（返回布尔值）
/// ```java
/// if (FeatureGate.isEnabled(Feature.BATCH_OPERATIONS)) {
///     // 执行批量操作
/// } else {
///     // 显示升级提示
/// }
/// ```
///
/// ### 方式2: 强制检查（抛出异常）
/// ```java
/// FeatureGate.requireFeature(Feature.TASK_MANAGEMENT);
/// // 如果许可证不支持，会抛出 FeatureNotLicensedException
/// ```
///
/// ### 方式3: 带回调的检查
/// ```java
/// FeatureGate.checkFeature(
///     Feature.ADVANCED_UI,
///     () -> showAdvancedSettings(),  // 如果启用
///     () -> showUpgradeDialog()       // 如果未启用
/// );
/// ```
@Slf4j
public class FeatureGate {

    /// 检查指定功能是否启用
    ///
    /// @param feature 要检查的功能
    /// @return 如果当前许可证支持该功能返回true
    public static boolean isEnabled(Feature feature) {
        var license = LicenseManager.getCurrentLicense();
        var isEnabled = feature.isAvailableIn(license.type());

        if (!isEnabled) {
            log.debug("功能 {} 未启用（需要: {}，当前: {}）",
                    feature.getDisplayName(),
                    feature.getRequiredLicense().getDisplayName(),
                    license.type().getDisplayName());
        }

        return isEnabled;
    }

    /// 要求功能必须启用，否则抛出异常
    ///
    /// 用于强制性的功能检查。如果功能未启用，会抛出异常。
    ///
    /// @param feature 要检查的功能
    /// @throws FeatureNotLicensedException 如果功能未启用
    public static void requireFeature(Feature feature) {
        if (!isEnabled(feature)) {
            throw new FeatureNotLicensedException(feature);
        }
    }

    /// 带回调的功能检查
    ///
    /// 根据功能是否启用，执行不同的回调函数。
    ///
    /// @param feature 要检查的功能
    /// @param enabledCallback 功能启用时执行的回调
    /// @param disabledCallback 功能未启用时执行的回调
    public static void checkFeature(
            Feature feature,
            Runnable enabledCallback,
            Runnable disabledCallback
    ) {
        if (isEnabled(feature)) {
            enabledCallback.run();
        } else {
            disabledCallback.run();
        }
    }

    /// 批量检查多个功能
    ///
    /// @param features 要检查的功能列表
    /// @return 如果所有功能都启用返回true
    public static boolean areAllEnabled(Feature... features) {
        for (var feature : features) {
            if (!isEnabled(feature)) {
                return false;
            }
        }
        return true;
    }

    /// 检查是否至少有一个功能启用
    ///
    /// @param features 要检查的功能列表
    /// @return 如果至少有一个功能启用返回true
    public static boolean isAnyEnabled(Feature... features) {
        for (var feature : features) {
            if (isEnabled(feature)) {
                return true;
            }
        }
        return false;
    }

    /// 获取功能不可用的原因描述
    ///
    /// @param feature 要检查的功能
    /// @return 如果功能不可用，返回原因描述；否则返回null
    public static String getDisabledReason(Feature feature) {
        if (isEnabled(feature)) {
            return null;
        }

        var license = LicenseManager.getCurrentLicense();
        return String.format(
                "「%s」功能需要 %s，当前使用 %s",
                feature.getDisplayName(),
                feature.getRequiredLicense().getDisplayName(),
                license.type().getDisplayName()
        );
    }

    /// 功能未授权异常
    ///
    /// 当尝试使用未授权的功能时抛出此异常。
    public static class FeatureNotLicensedException extends RuntimeException {
        private final Feature feature;

        public FeatureNotLicensedException(Feature feature) {
            super(FeatureGate.getDisabledReason(feature));
            this.feature = feature;
        }

        public Feature getFeature() {
            return feature;
        }
    }
}
